home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / strategy / vga_card.000 / vga_cardgames-1.3.1.tar / vga_cardgames / kllinux.c < prev    next >
C/C++ Source or Header  |  1995-02-26  |  13KB  |  554 lines

  1. /*
  2.  * Klondike
  3.  *
  4.  * Copyright (C) Evan Harris, 1991, 1994, 1995.
  5.  *
  6.  * Permission is granted to freely redistribute and modify this code,
  7.  * providing the author(s) get credit for having written it.
  8.  */
  9.  
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <vga.h>
  13. #include <vgamouse.h>
  14.  
  15. #include "vga16.h"
  16. #include "mouse.h"
  17. #include "key.h"
  18. #include "klondike.h"
  19. #include "common.h"
  20.  
  21.  
  22. #define KL_SCREENMODE G640x480x16
  23. #define KL_SCREENWIDTH 640
  24. #define KL_SCREENHEIGHT 480
  25.  
  26. #define KL_TEXTFG 1
  27. #define KL_TEXTBG 0
  28. #define KL_BUTTONFG 2
  29. #define KL_BUTTONBG 6
  30. #define KL_MOUSEFG 5
  31. #define KL_MOUSEDARKFG 2
  32. #define KL_OUTLINE 6
  33.  
  34. #define NUMCARDIMAGES 52
  35. #define CARDACTUALWIDTH 53
  36. #define CARDIMAGEWIDTH 56
  37. #define CARDIMAGEHEIGHT 80
  38.  
  39. #define VERSION "KLONDIKE\n  v1.3"
  40. #define VERSIONLEFT (KL_SCREENWIDTH - 72)
  41.  
  42. #ifndef CARDSFILE
  43. #define CARDSFILE "Cards56x80"
  44. #endif
  45. #ifndef CARDSMOUSESAMPLERATE
  46. #define CARDSMOUSESAMPLERATE MOUSE_DEFAULTSAMPLERATE
  47. #endif
  48.  
  49. #define USLEEP_TIME 30000
  50.  
  51.  
  52. #define CARDTOIMAGE(card)    (card % NUMCARDIMAGES)
  53.  
  54. #define BITWIDTH CARDIMAGEWIDTH /* multiple of 8 */
  55. #define BITHEIGHT CARDIMAGEHEIGHT
  56. #define BITSHOWLEFT 24        /* multiple of 8 */
  57. #define BITTOP 24
  58. #define COLWIDTH (BITWIDTH + 8)
  59. #define TOPROWHEIGHT    (BITHEIGHT + 4)
  60.  
  61.  
  62. #define KL_QUITLEFT (KL_SCREENWIDTH - 80)
  63. #define KL_QUITRIGHT (KL_QUITLEFT + 80)
  64. #define KL_QUITBOTTOM 104
  65. #define KL_QUITTOP (KL_QUITBOTTOM - 16)
  66.  
  67. #define KL_NEWGAMELEFT KL_QUITLEFT
  68. #define KL_NEWGAMERIGHT KL_QUITRIGHT
  69. #define KL_NEWGAMEBOTTOM 48
  70. #define KL_NEWGAMETOP (KL_NEWGAMEBOTTOM - 16)
  71.  
  72. #define KL_RESTARTLEFT KL_QUITLEFT
  73. #define KL_RESTARTRIGHT KL_QUITRIGHT
  74. #define KL_RESTARTBOTTOM 76
  75. #define KL_RESTARTTOP (KL_RESTARTBOTTOM - 16)
  76.  
  77.  
  78. #define STOCKLEFT 0
  79. #define STOCKTOP 0
  80. #define PILELEFT COLWIDTH
  81. #define PILETOP 0
  82. #define FOUNDLEFT (3 * COLWIDTH)
  83. #define FOUNDTOP 0
  84.  
  85.  
  86. #define KL_PALETTESIZE 7
  87.  
  88. int palette[KL_PALETTESIZE * 3] = {
  89.     0x00, 0x20, 0x00,        /* green */
  90.     0x3f, 0x3f, 0x3f,        /* white */
  91.     0x00, 0x00, 0x00,        /* black */
  92.     0x37, 0x00, 0x00,        /* red */
  93.     0x00, 0x00, 0x20,        /* blue */
  94.     0x2f, 0x3f, 0x00,        /* yellow */
  95.     0x1a, 0x1a, 0x1a,        /* grey */
  96. };
  97.  
  98. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  99. static void LoadCards(char *file);
  100. static long GetMouseButton(void);
  101. static long WhileMouseButton(void);
  102. static int ParsePos(long pos, int downcard, int buttonup);
  103.  
  104. static unsigned char ***imageCard;
  105. static unsigned char **backCard;
  106. static unsigned char **outlineCard;
  107. static unsigned char *blankLine;
  108.  
  109.  
  110. void
  111. InitDisplay(int argc, char **argv)
  112. {
  113.     vga_disabledriverreport();
  114.     vga_init();
  115. #if !defined(CARDSMOUSE)
  116.     vga_setmousesupport(1);
  117. #endif
  118.     
  119.     if (vga_setmode(KL_SCREENMODE) != 0) {
  120.     fprintf(stderr, "Mode %s not available!\n",
  121.         vga_getmodename(KL_SCREENMODE));
  122.     exit(1);
  123.     }
  124.  
  125. #if defined(CARDSMOUSE)
  126.     mouse_init("/dev/mouse", vga_getmousetype(), CARDSMOUSESAMPLERATE);
  127.     mouse_setxrange(0, KL_SCREENWIDTH - 1);
  128.     mouse_setyrange(0, KL_SCREENHEIGHT - 1);
  129.     mouse_setwrap(MOUSE_NOWRAP);
  130. #endif
  131.  
  132.     vga16_init();
  133.  
  134.     LoadCards(CARDSFILE);
  135.  
  136.     blankLine = (unsigned char *)calloc(KL_SCREENWIDTH, sizeof(unsigned char));
  137.     if (blankLine == NULL) {
  138.     fprintf(stderr, "Error: cannot get memory for blankLine\n");
  139.     exit(1);
  140.     }
  141.  
  142.     vga_setpalvec(0, KL_PALETTESIZE, &palette[0]);
  143.  
  144.     vga16_text(KL_NEWGAMELEFT, KL_NEWGAMEBOTTOM, " NEW GAME ",
  145.            KL_BUTTONFG, KL_BUTTONBG);
  146.     vga16_text(KL_RESTARTLEFT, KL_RESTARTBOTTOM, " RESTART  ",
  147.            KL_BUTTONFG, KL_BUTTONBG);
  148.     vga16_text(KL_QUITLEFT, KL_QUITBOTTOM, "   QUIT   ",
  149.            KL_BUTTONFG, KL_BUTTONBG);
  150.  
  151.     vga16_text(VERSIONLEFT, 200, VERSION, KL_TEXTFG, KL_TEXTBG);
  152. }
  153.  
  154.  
  155. static void
  156. LoadCards(char *file)
  157. {
  158.     int i, j, k, l, c, colour;
  159.     FILE *f;
  160.  
  161.     f = fopen(file, "r");
  162.     if (f == NULL) {
  163.     fprintf(stderr, "Cannot find '%s'\n", file);
  164.     exit(1);
  165.     }
  166.  
  167.     imageCard = (unsigned char ***)malloc(NUMCARDIMAGES
  168.                       * sizeof(unsigned char **));
  169.     if (imageCard == NULL) {
  170.     fprintf(stderr, "Error: cannot get memory for imageCard\n");
  171.     exit(1);
  172.     }
  173.     for (i = 0; i < NUMCARDIMAGES; i++) {
  174.     imageCard[i] = (unsigned char **)malloc(CARDIMAGEHEIGHT
  175.                         * sizeof(unsigned char *));
  176.     if (imageCard == NULL) {
  177.         fprintf(stderr, "Error: cannot get memory for imageCard[%d]\n",
  178.             i);
  179.         exit(1);
  180.     }
  181.     for (j = 0; j < CARDIMAGEHEIGHT; j++) {
  182.         imageCard[i][j] = (unsigned char *)malloc(CARDIMAGEWIDTH
  183.                               * sizeof(unsigned char));
  184.         if (imageCard[i][j] == NULL) { 
  185.         fprintf(stderr,
  186.             "Error: cannot get memory for imageCard[%d][%d]\n",
  187.             i, j);
  188.         exit(1);
  189.         }
  190.         
  191.         if (SUIT(i) == SPADES || SUIT(i) == CLUBS) {
  192.         colour = 2;
  193.         } else {
  194.         colour = 3;
  195.         }
  196.         if (TYPE(i) < JACK) {
  197.         for (k = 0; k < CARDIMAGEWIDTH / 8; k++) {
  198.             if ((c = getc(f)) == EOF) {
  199.             fprintf(stderr, "Unexpected EOF in '%s'\n", file);
  200.             exit(1);
  201.             }
  202.             for (l = 0; l < 8; l++) {
  203.             imageCard[i][j][8 * k + l] =
  204.                 (c & 1 << (7 - l)) ? colour : 1;
  205.             }
  206.         }
  207.         for (k = CARDACTUALWIDTH; k < CARDIMAGEWIDTH; k++) {
  208.             imageCard[i][j][k] = 0;
  209.         }
  210.         } else {
  211.         for (k = 0; k < CARDIMAGEWIDTH / 2; k++) {
  212.             if ((c = getc(f)) == EOF) {
  213.             fprintf(stderr, "Unexpected EOF in '%s'\n", file);
  214.             exit(1);
  215.             }
  216.             imageCard[i][j][2 * k] = (unsigned char)c >> 4;
  217.             imageCard[i][j][2 * k + 1] = (unsigned char)c & 0xf;
  218.         }
  219.         }
  220.     }
  221.     }
  222.  
  223.     fclose(f);
  224.  
  225.     backCard = malloc(CARDIMAGEHEIGHT * sizeof(unsigned char *));
  226.     outlineCard = malloc(CARDIMAGEHEIGHT * sizeof(unsigned char *));
  227.     if (backCard == NULL || outlineCard == NULL) {
  228.     fprintf(stderr, "Error: cannot get memory for cards");
  229.     exit(1);
  230.     }
  231.     for (i = 0; i < CARDIMAGEHEIGHT; i++) {
  232.     backCard[i] = malloc(CARDIMAGEWIDTH * sizeof(unsigned char));
  233.     outlineCard[i] = calloc(CARDIMAGEWIDTH, sizeof(unsigned char));
  234.     if (backCard[i] == NULL || outlineCard[i] == NULL) {
  235.         fprintf(stderr, "Error: cannot get memory for cards");
  236.         exit(1);
  237.     }
  238.     }
  239.     for (i = 0; i < CARDACTUALWIDTH; i++) {
  240.     outlineCard[0][i] = KL_OUTLINE;
  241.     outlineCard[CARDIMAGEHEIGHT - 1][i] = KL_OUTLINE;
  242.     }
  243.     for (i = 0; i < CARDIMAGEHEIGHT; i++) {
  244.     outlineCard[i][0] = KL_OUTLINE;
  245.     outlineCard[i][CARDACTUALWIDTH - 1] = KL_OUTLINE;
  246.     }
  247.     for (i = 0; i < CARDIMAGEHEIGHT; i++) {
  248.     for (j = 0; j < CARDACTUALWIDTH; j++) {
  249.         if ((i / 4) % 2 == (j / 4) % 2) {
  250.         backCard[i][j] = 4;
  251.         } else {
  252.         backCard[i][j] = 1;
  253.         }
  254.     }
  255.     for (; j < CARDIMAGEWIDTH; j++) {
  256.         backCard[i][j] = 0;
  257.     }
  258.     }
  259. }
  260.  
  261.  
  262. static unsigned char columnTop[COLUMNS];
  263.  
  264. /* We redisplay a whole column, rather than do anything tricky. */
  265. void
  266. DisplayColumn(short col)
  267. {
  268.     unsigned char **image;
  269.     int card, length, row, height, line;
  270.     int bittop = BITTOP;
  271.     
  272.     if (col == STOCK || col == PILE) {
  273.     DisplayStockPile();
  274.     return;
  275.     }
  276.  
  277.     for (card = column[col], length = 0; card != NOCARD; card = next[card])
  278.     length++;
  279.  
  280.     if (length > 0 && (KL_SCREENHEIGHT - TOPROWHEIGHT) / length < bittop)
  281.     bittop = (KL_SCREENHEIGHT - TOPROWHEIGHT) / length;
  282.     columnTop[col] = bittop;
  283.  
  284.     card = column[col];
  285.     row = TOPROWHEIGHT;
  286.     col = col * COLWIDTH;
  287.  
  288.     while (card != NOCARD && row < KL_SCREENHEIGHT - 1) {
  289.     if (hidden[card])
  290.         image = backCard;
  291.     else
  292.         image = imageCard[CARDTOIMAGE(card)];
  293.     if (next[card] == NOCARD)
  294.         height = BITHEIGHT;
  295.     else
  296.         height = bittop;
  297.     if (row + height >= KL_SCREENHEIGHT)
  298.         height -= row + height - KL_SCREENHEIGHT + 1;
  299.  
  300.     for (line = 0; line < height; line++) {
  301.         vga16_drawscansegment(image[line], col, row + line, BITWIDTH);
  302.     }
  303.  
  304.     row += height;
  305.     card = next[card];
  306.     }
  307.     for (; row < KL_SCREENHEIGHT; row++) {
  308.     vga16_drawscansegment(blankLine, col, row, BITWIDTH);
  309.     }
  310.  
  311.     return;
  312. }
  313.  
  314.  
  315. void
  316. DisplayStockPile()
  317. {
  318.     unsigned char **card;
  319.     int line;
  320.     
  321.     if (stock == NOCARD) {
  322.     card = outlineCard;
  323.     } else {
  324.     card = backCard;
  325.     }
  326.     for (line = 0; line < CARDIMAGEHEIGHT; line++) {
  327.     vga16_drawscansegment(card[line], STOCKLEFT, STOCKTOP + line,
  328.                   BITWIDTH);
  329.     }
  330.     if (pile == NOCARD) {
  331.     card = outlineCard;
  332.     } else {
  333.     card = imageCard[CARDTOIMAGE(pile)];
  334.     }
  335.     for (line = 0; line < CARDIMAGEHEIGHT; line++) {
  336.     vga16_drawscansegment(card[line], PILELEFT, PILETOP + line, BITWIDTH);
  337.     }
  338. }
  339.  
  340.  
  341. void
  342. DisplayFoundations()
  343. {
  344.     unsigned char **card;
  345.     int i, line, foundleft;
  346.  
  347.     foundleft = FOUNDLEFT;
  348.     for (i = 0; i < NUMSUITS; i++) {
  349.     if (foundation[i] == 0) {
  350.         card = outlineCard;
  351.     } else {
  352.         card = imageCard[CARD(i % 4, foundation[i] - 1)];
  353.     }
  354.     for (line = 0; line < CARDIMAGEHEIGHT; line++) {
  355.         vga16_drawscansegment(card[line], foundleft, FOUNDTOP + line,
  356.                   BITWIDTH);
  357.     }
  358.     foundleft += COLWIDTH;
  359.     }
  360. }
  361.  
  362.  
  363. short
  364. GetCmd()
  365. {
  366.     int c, c1;
  367.     
  368.     for (c = NOCARD; c == NOCARD;) {
  369.     c = GetMouseButton();
  370.     c1 = WhileMouseButton();
  371.     if (c >= 0) {
  372.         c = ParsePos(c, -1, 0);
  373.         c1 = ParsePos(c1, c, 1);
  374.  
  375.         if (c == c1 && (c >= 0 || c == FROMSTOCK)) {
  376.         return c;
  377.         }
  378.         if (c >= 0 && c1 == TOFOUNDATION) {
  379.         return TOHINT(FOUNDATION) | c;
  380.         }
  381.         if (c >= 0 && ISCOLSPEC(c1)) {
  382.         return TOHINT(SPECTOCOL(c1)) | c;
  383.         }
  384.         
  385.         c = NOCARD;
  386.     }
  387.     }
  388.  
  389.     return c;
  390. }
  391.  
  392.  
  393. static int oldx = -1, oldy, oldcolour[40];
  394.  
  395. static long
  396. GetMouseButton()
  397. {
  398.     int x, y, button, key;
  399.  
  400.     x = mouse_getx();
  401.     y = mouse_gety();
  402.     if (x != oldx || y != oldy) {
  403.     if (oldx != -1) {
  404.         RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
  405.     }
  406.     SaveUnderMousePointer(x, y, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
  407.     RenderMousePointer(x, y, KL_MOUSEFG, KL_MOUSEDARKFG, KL_SCREENWIDTH, KL_SCREENHEIGHT);
  408.     oldx = x;
  409.     oldy = y;
  410.     }
  411.     
  412.     for (;;) {
  413.     usleep(USLEEP_TIME);    /* don't chew up as much CPU */
  414.  
  415.     if (mouse_update()) {
  416.         x = mouse_getx();
  417.         y = mouse_gety();
  418.         button = mouse_getbutton();
  419.  
  420.         if (x != oldx || y != oldy) {
  421.         if (oldx != -1) {
  422.             RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
  423.         }
  424.         SaveUnderMousePointer(x, y, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
  425.         RenderMousePointer(x, y, KL_MOUSEFG, KL_MOUSEDARKFG, KL_SCREENWIDTH, KL_SCREENHEIGHT);
  426.         oldx = x;
  427.         oldy = y;
  428.         }
  429.     
  430.         if (button & MOUSE_LEFTBUTTON) {
  431.         break;
  432.         }
  433.     }
  434.     if ((key = key_getkey()) != -1) {
  435.         switch (key) {
  436.           case 'n':
  437.           case 'N':
  438.         return NEWGAME;
  439.           case 'r':
  440.           case 'R':
  441.         return RESTART;
  442.           case 'q':
  443.           case 'Q':
  444.         return QUIT;
  445.           case '\014':
  446.         vga16_redrawscreen();
  447.         break;
  448.           default:
  449.         break;
  450.         }
  451.     }
  452.     }
  453.  
  454.     if (x >= KL_NEWGAMELEFT && x < KL_NEWGAMERIGHT
  455.     && y > KL_NEWGAMETOP && y <= KL_NEWGAMEBOTTOM) {
  456.     return NEWGAME;
  457.     }
  458.     if (x >= KL_RESTARTLEFT && x < KL_RESTARTRIGHT
  459.     && y > KL_RESTARTTOP && y <= KL_RESTARTBOTTOM) {
  460.     return RESTART;
  461.     }
  462.     if (x >= KL_QUITLEFT && x < KL_QUITRIGHT
  463.     && y > KL_QUITTOP && y <= KL_QUITBOTTOM) {
  464.     return QUIT;
  465.     }
  466.  
  467.     return (x << 9) | y;
  468. }
  469.  
  470.  
  471. static long
  472. WhileMouseButton()
  473. {
  474.     int x, y, button;
  475.  
  476.     for (;;) {
  477.     usleep(USLEEP_TIME);    /* don't chew up as much CPU */
  478.  
  479.     mouse_update();
  480.     x = mouse_getx();
  481.     y = mouse_gety();
  482.     button = mouse_getbutton();
  483.  
  484.     if (x != oldx || y != oldy) {
  485.         if (oldx != -1) {
  486.         RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
  487.         }
  488.         SaveUnderMousePointer(x, y, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
  489.         RenderMousePointer(x, y, KL_MOUSEFG, KL_MOUSEDARKFG, KL_SCREENWIDTH, KL_SCREENHEIGHT);
  490.         oldx = x;
  491.         oldy = y;
  492.     }
  493.     
  494.     if (!(button & MOUSE_LEFTBUTTON)) {
  495.         break;
  496.     }
  497.     }
  498.  
  499.     if (oldx != -1) {
  500.     RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
  501.     }
  502.     oldx = -1;
  503.  
  504.     return (x << 9) | y;
  505. }
  506.  
  507.  
  508. static int
  509. ParsePos(long pos, int downcard, int buttonup)
  510. {
  511.     int x, y, card, row, bittop;
  512.     
  513.     x = pos >> 9;
  514.     y = pos & 0x1ff;
  515.     if (x >= STOCKLEFT && x < STOCKLEFT + BITWIDTH
  516.     && y >= STOCKTOP && y < STOCKTOP + CARDIMAGEHEIGHT) {
  517.     return FROMSTOCK;
  518.     }
  519.     if (x >= STOCKLEFT + COLWIDTH && x < STOCKLEFT + COLWIDTH + BITWIDTH
  520.     && y >= STOCKTOP && y < STOCKTOP + CARDIMAGEHEIGHT) {
  521.     return pile;
  522.     }
  523.     if (buttonup
  524.     && x >= FOUNDLEFT && x < FOUNDLEFT + NUMSUITS * COLWIDTH
  525.     && y >= FOUNDTOP && y < FOUNDTOP + CARDIMAGEHEIGHT) {
  526.     return TOFOUNDATION;
  527.     }
  528.  
  529.     if (x / COLWIDTH > 6 || y < TOPROWHEIGHT ||
  530.     (x % COLWIDTH) / BITWIDTH > 0) {
  531.     return NOCARD;
  532.     }
  533.  
  534.     card = column[x / COLWIDTH];
  535.     bittop = columnTop[x / COLWIDTH];
  536.     row = TOPROWHEIGHT;
  537.  
  538.     while (card != NOCARD) {
  539.     if ((next[card] != NOCARD && y >= row && y < row + bittop)
  540.         || (next[card] == NOCARD && y >= row && y < row + BITHEIGHT)) {
  541.         if (!hidden[card] && (downcard == -1 || downcard == card)) {
  542.         return card;
  543.         }
  544.     }
  545.     card = next[card];
  546.     row += bittop;
  547.     }
  548.     if (buttonup) {
  549.     return COLTOSPEC(x / COLWIDTH);
  550.     }
  551.  
  552.     return NOCARD;
  553. }
  554.